import os
import datetime, hashlib
import urllib
import tornado
from whirlwind.core.request import BaseRequest
from whirlwind.db.mongo import Mongo
from application.models.user import User
from application.models.user import simple_email_validator
from tornado.options import options
from tornado.auth import GoogleMixin
from tornado.web import authenticated
from whirlwind.view.decorators import route
from HandlerExtension.BasicHandler import BasicHandler
from EmailExtension.EmailExtension import CurrentEmailSender
from UtilExtension.GenRandPassword import generate_password
from mako.template import Template

@route('/account/logout')
class LogoutHandler(BasicHandler):
    def get(self):
        #kill the session.
        self.session['email'] = None
        self.session.destroy()
        #clear cookie
        self.clear_cookie('email')
        self.redirect("/")

@route('/account/login')
class LoginHandler(BasicHandler):
    def get(self):
        template_values = {}
        template_values['next'] = self.get_argument('next','/')
        
        self.render_template('/account/login.html',**template_values)
        
    def post(self):
        email = self.get_argument("email",None)
        password = self.get_argument("password",None)
        
        if not email or not password:
            # do something
            self.flash.error = "You must enter your email and password to proceed. Please try again."
            self.redirect("/account/login")
            return
        
        pw = User.hash_password(password)
        user = User.lookup(email)
        
        #check the password.
        if not user or user['password'] != pw:
            # do something
            self.flash.error = "Login not valid"
            self.redirect("/account/login")
            return
        
        # check if user is suspended.
        if user.is_suspended() :
            self.flash.error = "Sorry the account you specified has been suspended."
            self.redirect("/")
            return
          

        user.history.last_login = datetime.datetime.utcnow()
        user.history.num_logins += 1
        user.save()
        
        #add to the session.
        self.session['username'] = user.username
        self.session['email'] = user._id
        self.session['locale'] = user.profile.locale
        #check keep_logged_in
        if self.get_argument("keep_logged_in", False) == "on" :
            self.session['keep_logged_in'] = True
            # write cookie
            self.set_secure_cookie('email', user._id)
        
        #self.set_current_user(user)
        self.flash.notice = "Welcome, %s" % user.username
        forwardUrl = self.get_argument('next','/')
        self.redirect(forwardUrl)

@route('/account/signup')
class SignupHandler(BasicHandler):
    def get(self):
        template_values = {}
        template_values['next'] = self.get_argument('next','/')
        
        self.render_template('/account/signup.html',**template_values)
    
    def post(self):
        password = self.get_argument("password",None)
        email = self.get_argument("email",None)
        
        if not password or not email:
            # do something
            self.flash.error = "You must enter a email and password to proceed. Please try again."
            self.redirect("/account/signup")
            return
        
        if password != self.get_argument("password2", None) :
            self.flash.error = "Passwords do not match. Please try again."
            self.redirect("/account/signup")
            return
        
        if email != self.get_argument("email2", None) :
            self.flash.error = "Email address do not match. Please try again."
            self.redirect("/account/signup")
            return

        username = User.extract_username(email)
        user = User.instance(username, password, email)
        user.validate()
        if user.validation_errors:
            errors = user.validation_errors.itervalues()
            for v in errors:
                self.flash.error = str(v[0]).split(':')[1].strip()
                break
            self.redirect("/account/signup")
            return
        user.save()
        # Send activation email
        activationEmail = Template(filename=options.template_dir + '/email/activation.html')
        email_data = {}
        account_data = {}
        account_data['email'] = user._id.encode('utf-8')
        account_data['tempcode'] = user.password.encode('utf-8')
        email_data['username'] = user.username
        email_data['activate_link'] = "%s?%s" % (
                str(options.domain) + ':' + str(options.port) + '/account/activate', \
                urllib.urlencode(account_data))
        sender = CurrentEmailSender()
        sender.SendEmail([user._id], "Soy Platform Activation",
                         activationEmail.render(**email_data))
        self.flash.info = "Successfully created your account, please check \
                your email box to activate your account!"
        self.redirect("/")


@route('/account/activate')
class AccountActiveHandler(BasicHandler):
    """
    Handle the activate account request.
    """
    def get(self):
        email = self.get_argument('email', None)
        password = self.get_argument('tempcode', None)
        if not email or not password:
            self.flash.error = "You activation link is invalid!"
            self.redirect("/")
            return
        email = email.decode('utf-8')
        password = password.decode('utf-8')
        if not User.email_exist(email):
            self.flash.error = "You activation link is invalid!"
            self.redirect("/")
            return
        user = User.lookup(email)
        if password != user.password:
            self.flash.error = "You activation link is invalid!"
            self.redirect("/")
            return
        if not user.has_role('nonactive'):
            self.flash.error = "You have already activated!"
            self.redirect("/")
            return
        user.remove_role('nonactive')
        user.add_role('basic')
        user.save()
        self.flash.info = "Congratulations! You have activate your account Successfully!"
        # Maybe redirect to profile page
        self.redirect('/')
        return


@route('/account/googlelogin')
class GoogleLoginHandler(BasicHandler, GoogleMixin):
    """
    Request Handler for google auth.
    """
    @tornado.web.asynchronous
    def get(self):
        if self.get_argument("openid.mode", None):
            self.get_authenticated_user(self.async_callback(self._on_auth))
            return
        self.authenticate_redirect()
        
        
    def _on_auth(self, user):
        if not user:
            raise tornado.web.HTTPError(500, "Google auth failed")
        email = user['email']
        username = user['name']
        locale = user['locale']

        if not User.email_exist(email):
            # Add new user
            username = User.extract_username(email)
            password = generate_password(8)
            user = User.instance(username, password, email)
            user.profile.locale = locale
            user.save()
            # Send activation email
            activationEmail = Template(filename=options.template_dir +
                                       '/email/gmail_activation.html')
            email_data = {}
            account_data = {}
            account_data['email'] = user._id.encode('utf-8')
            account_data['tempcode'] = user.password.encode('utf-8')
            email_data['username'] = unicode(user.username)
            email_data['password'] = unicode(password)
            email_data['password_link'] = str(options.domain) + ':' + \
                    str(options.port) + '/account/changepassword'
            email_data['activate_link'] = "%s?%s" % (
                    str(options.domain) + ':' + str(options.port) + '/account/activate', \
                    urllib.urlencode(account_data))
            sender = CurrentEmailSender()
            sender.SendEmail([user._id], "Soy Platform Activation",
                             activationEmail.render(**email_data))
            self.flash.info = "Successfully created your account, please check \
                    your email box to activate your account!"

        user = User.lookup(email)
        #add to the session.
        self.session['username'] = user.username
        self.session['email'] = user._id
        self.session['locale'] = user.profile.locale
                
        #self.set_current_user(user)
        self.flash.notice = "Welcome, %s" % user.username
        forwardUrl = self.get_argument('next','/')
        self.redirect(forwardUrl)
        # Add session
        # Save the user with, e.g., set_secure_cookie()

@route("/account/changepassword")
class PasswordChangerHandler(BasicHandler):
    @authenticated
    def get(self):
        template_values = {}
        self.render_template('/account/change_password.html',**template_values)

    @authenticated
    def post(self):
        user = self.get_current_user()
        pw = User.hash_password(self.get_argument("password"))
        
        if user.password != unicode(pw):
            # do something
            self.flash.error = "Password not valid, please try again"
            self.redirect("/settings")
            return
        
        newPw = self.get_argument('new_pw')
        newPw2 = self.get_argument('new_pw_again')
        if newPw != newPw2 :
            self.flash.error = "Passwords do not match, please try again"
            self.redirect("/settings")
            return
        
        password = User.hash_password(newPw)
        user.password = unicode(password)
        user.save()
        self.flash.success = "Successfully updated password"
        self.redirect('/')

@route("/account/forgetpassword")
class ForgetPasswordHandler(BasicHandler):
    """
    Handler for forget password
    """
    def get(self):
        template_values = {}
        self.render_template('/account/forget_password.html',**template_values)

    def post(self):
        email = self.get_argument('email')
        try:
            simple_email_validator(email)
        except:
            self.flash.error = "Email is not valid"
            self.redirect('/')
            return
        user = User.lookup(email)
        if not user: 
            self.flash.error = "This email has not been registered yet!"
            self.redirect('/')
            return
        
        password = generate_password(8)
        user.password = User.hash_password(password)
        user.save()
        # Send temp password email
        passwordEmail = Template(filename=options.template_dir +
                                   '/email/temp_password.html')
        email_data = {}
        email_data['username'] = unicode(user.username)
        email_data['password'] = unicode(password)
        sender = CurrentEmailSender()
        sender.SendEmail([user._id], "Soy Platform Temp Password",
                         passwordEmail.render(**email_data))
        self.flash.info = "Email with temp password was send to \
                your email box! You can login with temp password \
                and then change the password"
        self.redirect('/account/login')
